package com.frank.loadinglibrary.common;

import com.frank.loadinglibrary.utils.Indicator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.ArrayList;

public class BallBeatLoadComponent extends BallLoadingComponent implements Component.DrawTask {

    public static HiLogLabel label = new HiLogLabel(HiLog.DEBUG, 1, "TAG");

    public static final float SCALE = 1.0f;

    public static final float ALPHA = 1.0f;

    //scale x ,y
    public float[] scaleFloats;

    //scale x ,y
    public float[] alphaFloats;

    //设置动画的执行时间
    private int durtion = BASE_DURTION_TIME;

    //设置延时动画的时间基准
    private int delayTime = BASE_DELAY_TIME;

    //设置允许的最大个数
    private static final int MAX_COUNT = 7;
    //设置允许的最大个数
    private static final int DEFAULT_COUNT = 3;

    //延时基数
    private static final int BASE_DELAY_TIME = 120;
    //默认时长基数
    private static final int BASE_DURTION_TIME = 1000;

    private Paint mPaint;

    //动画执行指示器
    protected Indicator indicator;

    //左右边距
    private static final float DEFAULT_MAGIN_HOR = 10;

    //半径
    private float radius = 0;

    //水平间隔
    private float spacing_hor = 10;

    public BallBeatLoadComponent(Context context) {
        this(context, null);
    }

    public BallBeatLoadComponent(Context context, AttrSet attrSet) {
        this(context, attrSet, "");

    }

    public BallBeatLoadComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    public BallBeatLoadComponent(Context context, AttrSet attrSet, int resId) {
        super(context, attrSet, resId);
        init();
    }

    @Override
    public BallBeatLoadComponent setBallCount(int ballCount) {
        super.setBallCount(ballCount);
        scaleFloats = new float[getBallCount()];
        alphaFloats = new float[getBallCount()];
        for (int i = 0; i < getBallCount(); i++) {
            scaleFloats[i] = SCALE;
            alphaFloats[i] = ALPHA;
        }
        return this;
    }

    private void init() {
        setBallCount(DEFAULT_COUNT);
        setDurtion(BASE_DURTION_TIME);
        addDrawTask(this);
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                if (autoStart) {
                    startAnimators();
                }
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });

        indicator = new Indicator<AnimatorValue>() {
            @Override
            public ArrayList<AnimatorValue> onCreateAnimators() {
                return BallBeatLoadComponent.this.onCreateAnimators();
            }
        };
    }

    private ArrayList<AnimatorValue> onCreateAnimators() {
        ArrayList<AnimatorValue> animators = new ArrayList<>();
        if (BASE_DELAY_TIME * getBallCount() > durtion) {
            //设置时长的3/4 为基准线去计算延时时间
            delayTime = durtion * 3 / 4 / getBallCount();
        }
        for (int i = 0; i < getBallCount(); i++) {
            final int index = i;
            AnimatorValue scaleAnim = new AnimatorValue();
            scaleAnim.setDuration(durtion);
            scaleAnim.setLoopedCount(-1);
            scaleAnim.setDelay(delayTime * (i + 1));
            indicator.addUpdateListener(scaleAnim, (animatorValue, v) -> {
                //设定 0.3 - 1之间缩放
                if (v < 0.5f)
                    scaleFloats[index] = (float) (-1.4 * v + 1);
                else
                    scaleFloats[index] = (float) (1.4 * v - 0.4);
                invalidate();
            });

            if (enableAlphaAnimator) {
                AnimatorValue alphaAnim = new AnimatorValue();
                alphaAnim.setDuration(durtion);
                alphaAnim.setLoopedCount(-1);
                alphaAnim.setDelay(delayTime * (i + 1));
                indicator.addUpdateListener(alphaAnim, (animatorValue, v) -> {
                    if (v < 0.5f)
                        alphaFloats[index] = (float) (-408 * v + 255) / 255;
                    else
                        alphaFloats[index] = (float) (408 * v - 153) / 255;
                    invalidate();
                });
                animators.add(alphaAnim);

            }
            animators.add(scaleAnim);
        }
        return animators;
    }

    @Override
    public void stopAnimators() {
        indicator.stop();
        invalidate();
    }

    @Override
    public void startAnimators() {
        indicator.start();
    }

    @Override
    protected void releaseSource() {

    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        HiLog.debug(label, "onDraw");
        if (mPaint == null) {
            setPaint();
        }
        draw(canvas, mPaint);
    }

    private void draw(Canvas canvas, Paint paint) {
        if (radius <= 0) {
            //如果没有给定半径，则以宽度250 边距10 间距10  进行计算 半径
            radius = (getWidth() - (getWidth() / 250.f) * spacing_hor * (getBallCount() - 1) - DEFAULT_MAGIN_HOR * 2) / (getBallCount() * 2);
        } else {
            //给定半径 根据半径 以25个像素半径间距10为基准线计算间距
            spacing_hor = radius * 10 / 25;
        }
        float x = 0;
        float y = 0;
        //根据球的个数计算第一个球的起始位置
        if (getBallCount() % 2 == 0) {
            x = getWidth() / 2 - (getBallCount() * radius - (getBallCount() / 2 - 1) * spacing_hor - spacing_hor / 2);
            y = getHeight() / 2;
        } else {
            x = getWidth() / 2 - (getBallCount() * radius - getBallCount() / 2 * spacing_hor);
            y = getHeight() / 2;
        }
        HiLog.debug(label, "draw radius = " + radius + " getWidth is " + getWidth() + " x_y:" + x + ":" + y);
        for (int i = 0; i < getBallCount(); i++) {
            canvas.save();
            Color currentColor = Color.WHITE;
            if (colorPalette != null && colorPalette.length > 0) {
                currentColor = new Color(Color.getIntColor(colorPalette[i % colorPalette.length]));
            }
            paint.setColor(currentColor);
            float translateX = x + (radius * 2) * i + spacing_hor * i;
            canvas.translate(translateX, y);
            canvas.scale(scaleFloats[i], scaleFloats[i]);
            paint.setAlpha(alphaFloats[i]);
            canvas.drawCircle(0, 0, radius, mPaint);
            canvas.rotate(60);
            canvas.restore();
        }
    }

    public void setPaint() {
        if (mPaint == null) {
            mPaint = new Paint();
            mPaint.setColor(Color.WHITE);
            mPaint.setStyle(Paint.Style.FILL_STYLE);
            mPaint.setAntiAlias(true);
        }
    }

    public BallBeatLoadComponent setRadius(float radius) {
        this.radius = radius;
        return this;
    }
}
